package com.winchain.chainbill.serfee.service.impl;

import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.base.utils.MoneyUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.file.po.PubFile;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.feign.PubUserFeign;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.MessageSender;
import com.shell.framework.utils.SysDateUtil;
import com.shell.governor.modules.message.keyword.SmsPaySerFeeFailKeyword;
import com.shell.governor.user.po.PubUser;
import com.winchain.chainbill.basic.charge.dao.ValRetBizDao;
import com.winchain.chainbill.basic.charge.po.ValRetBiz;
import com.winchain.chainbill.basic.charge.service.ValRetBizService;
import com.winchain.chainbill.basic.cus.po.CusRec;
import com.winchain.chainbill.basic.cus.service.CusRecService;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.base.service.CbRecService;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillEvent;
import com.winchain.chainbill.bill.biz.send.rx.BillMoveSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.BillOptSubscriber;
import com.winchain.chainbill.serfee.rx.BillDctReAprvDeductSerFeeSubscriber;
import com.winchain.chainbill.serfee.rx.BillDctReAprvSignDebitCertSubscriber;
import com.winchain.chainbill.serfee.rx.BillDctUpdateSerFeeSubscriber;
import com.winchain.chainbill.serfee.rx.BillReAprvMsgSubscriber;
import com.winchain.chainbill.serfee.rx.TBillDctReAprvDeductSerFeeSubscriber;
import com.winchain.chainbill.serfee.rx.TBillDctReAprvSignDebitCertSubscriber;
import com.winchain.chainbill.serfee.rx.TBillDctUpdateSerFeeSubscriber;
import com.winchain.chainbill.serfee.rx.TBillReAprvMsgSubscriber;
import com.winchain.chainbill.serfee.service.ServiceFeeService;
import com.winchain.chainbill.serfee.vo.SerFeeVo;
import com.winchain.chainbill.tbill.base.po.TbDct;
import com.winchain.chainbill.tbill.base.po.TbOpt;
import com.winchain.chainbill.tbill.base.po.TbRec;
import com.winchain.chainbill.tbill.base.po.TbSnd;
import com.winchain.chainbill.tbill.base.service.TbDctService;
import com.winchain.chainbill.tbill.base.service.TbRecService;
import com.winchain.chainbill.tbill.base.service.TbSndService;
import com.winchain.chainbill.tbill.basic.rx.TBillMoveSubscriber;
import com.winchain.chainbill.tbill.basic.rx.TBillOptSubscriber;
import com.winchain.chainbill.tbill.biz.TBill;
import com.winchain.chainbill.tbill.biz.TBillEvent;
import com.winchain.chainbill.trade.service.BillAcctService;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import rx.Observable;

@Service
public class ServiceFeeServiceImpl implements ServiceFeeService {
	private static final String DATE_FORMAT = "yyyy��MM��dd��";
	@Autowired
	private ValRetBizDao valRetBizDao;
	@Autowired
	private ValRetBizService valRetBizService;
	@Autowired
	private PubUserFeign pubUserFeign;
	@Autowired
	private CbDctService cbDctService;
	@Autowired
	private CbRecService cbRecService;
	@Autowired
	private TbDctService tbDctService;
	@Autowired
	private TbRecService tbRecService;
	@Autowired
	private TbSndService tbSndService;
	@Autowired
	private TBillOptSubscriber tBillOptSubscriber;
	@Autowired
	private TBillMoveSubscriber tBillMoveSubscriber;
	@Autowired
	private TBillDctReAprvDeductSerFeeSubscriber tBillDctReAprvDeductSerFeeSubscriber;
	@Autowired
	private TBillDctUpdateSerFeeSubscriber tBillDctUpdateSerFeeSubscriber;
	@Autowired
	private TBillReAprvMsgSubscriber tBillReAprvMsgSubscriber;
	@Autowired
	private BillDctReAprvDeductSerFeeSubscriber billDctReAprvDeductSerFeeSubscriber;
	@Autowired
	private BillDctUpdateSerFeeSubscriber billDctUpdateSerFeeSubscriber;
	@Autowired
	private BillReAprvMsgSubscriber billReAprvMsgSubscriber;
	@Autowired
	private BillOptSubscriber billOptSubscriber;
	@Autowired
	private BillMoveSubscriber billMoveSubscriber;
	@Autowired
	private CusRecService cusRecService;
	@Autowired
	private BillAcctService billAcctService;
	@Autowired
	private BillDctReAprvSignDebitCertSubscriber billDctReAprvSignDebitCertSubscriber;
	@Autowired
	private TBillDctReAprvSignDebitCertSubscriber tBillDctReAprvSignDebitCertSubscriber;
	@Autowired
	private ServiceFeeAttService serviceFeeAttService;

	@Pagination
	public List<SerFeeVo> queryServiceFeePayConfirmList(PageLimit limit, String bizType, String cusName) {
		if (StringUtil.notEmpty(cusName)) {
			cusName = StringUtil.getParameterLike(cusName);
		}
		return this.valRetBizDao.queryServiceFeePayConfirmist(bizType, cusName);
	}

	public SerFeeVo detail(String dctId, String bizType) {
		SerFeeVo serFeeVo;
		if ("0".equals(bizType)) {
			serFeeVo = this.valRetBizDao.getBillServiceFeeConfirmDetail(dctId);
		} else {
			serFeeVo = this.valRetBizDao.getTBillServiceFeeConfirmDetail(dctId);
			TbRec rec = (TbRec) this.tbRecService.selectByKey(serFeeVo.getBillId());
			serFeeVo.setTbRec(rec);
			TbSnd snd = this.tbSndService.selectByBillId(serFeeVo.getBillId());
			serFeeVo.setTbSnd(snd);
		}
		if (StringUtil.notEmpty(serFeeVo.getCreatorId())) {
			PubUser user = this.pubUserFeign.selectByKey(serFeeVo.getCreatorId());
			serFeeVo.setCreatorName(user.getUserName());
			serFeeVo.setPhoneNo(user.getPhoneNo());
		}
		return serFeeVo;
	}

	public int getMsgCountForServiceFee(String cusId) {
		return this.valRetBizDao.getMsgCountForServiceFee();
	}

	@Pagination
	public List<SerFeeVo> queryServiceFeePaySuccessList(PageLimit limit, String bizType, String cusName) {
		if (StringUtil.notEmpty(cusName)) {
			cusName = StringUtil.getParameterLike(cusName);
		}
		return this.valRetBizDao.queryServiceFeePaySuccessList(bizType, cusName);
	}

	public PubFile genDebitCert(String dctId, String bizType) {
		return this.serviceFeeAttService.genDebitCert(dctId, bizType);
	}

	public RetMsg success(String dctId, String bizType) {
		if ("0".equals(bizType)) {
			confirmBillServiceFee(dctId);
		} else {
			confirmTBillServiceFee(dctId);
		}
		return new RetMsg("success", false, "����������");
	}

	public RetMsg fail(String dctId, String bizType, String remark) {
		String sellerNm;
		String billCode;
		String buyerId;
		String zyMessageTemplate;
		String template;
		BigDecimal dctAmt;
		BigDecimal serFee;
		String dctDate;
		int dctDays;
		if ("0".equals(bizType)) {
			CbDct dct = (CbDct) this.cbDctService.selectByKey(dctId);
			CbRec rec = (CbRec) this.cbRecService.selectByKey(dct.getBillId());
			billCode = rec.getBillCode();
			buyerId = dct.getBuyerId();
			zyMessageTemplate = "MT09014";
			template = "MT09013";
			dctAmt = dct.getDctAmt();
			serFee = dct.getSerFee();
			dctDate = dct.getDctDate();
			dctDays = dct.getDctDays().intValue();
			sellerNm = dct.getSellerNm();
		} else {
			TbDct dct = (TbDct) this.tbDctService.selectByKey(dctId);
			TbRec rec = (TbRec) this.tbRecService.selectByKey(dct.getBillId());
			billCode = rec.getBillCode();
			buyerId = dct.getBuyerId();
			zyMessageTemplate = "MT09017";
			if (dct.getBuyerId().equals(dct.getSellerId())) {
				template = "MT09018";
			} else {
				template = "MT09020";
			}
			dctAmt = dct.getDctAmt();
			serFee = dct.getSerFee();
			dctDate = dct.getDctDate();
			dctDays = dct.getDctDays().intValue();
			sellerNm = dct.getSellerNm();
		}
		String senderId = CommonDataUtil.getUserId();
		CusRec artisan = this.cusRecService.getArtisan(null);
		AcctBas buyerAcct = this.billAcctService.getAcctBas(buyerId, null, "00");
		SmsPaySerFeeFailKeyword keyword = new SmsPaySerFeeFailKeyword();
		keyword.setBillCode(billCode);
		keyword.setCusName(sellerNm);
		keyword.setBillAmt(MoneyUtil.format(dctAmt));
		keyword.setSerFee(MoneyUtil.format(serFee));
		keyword.setDctDate(SysDateUtil.parseDate(dctDate, "yyyyMMdd", "yyyy-MM-dd"));
		keyword.setDctDays(dctDays + "");
		keyword.setRemark(remark);
		keyword.setAcctNo(buyerAcct.getAcctNo());
		MessageSender.sendMessageByTmpl(senderId, template, keyword, buyerId);

		MessageSender.sendMessageByTmpl(senderId, zyMessageTemplate, keyword, artisan.getCusId());
		return new RetMsg("success", false, "����������");
	}

	private void confirmTBillServiceFee(String dctId) {
		TbDct dct = (TbDct) this.tbDctService.selectByKey(dctId);
		TbRec rec = (TbRec) this.tbRecService.selectByKey(dct.getBillId());
		TbOpt opt = new TbOpt();
		opt.setCurState(rec.getBillState());
		opt.setLimDate("");
		opt.setOptCode("E004");
		opt.setRemark("������������������");

		TBill<TbDct> bill = new TBill();
		bill.setSource(dct);
		bill.setRec(rec);
		TBillEvent<TbDct> event = new TBillEvent(bill);
		event.setOperation(opt);
		event.setValue("serFeeBizState", "1");
		Observable<TBillEvent<TbDct>> observers = Observable.just(event);

		observers.subscribe(this.tBillOptSubscriber);
		observers.subscribe(this.tBillMoveSubscriber);
		observers.subscribe(this.tBillDctReAprvSignDebitCertSubscriber);
		observers.subscribe(this.tBillDctReAprvDeductSerFeeSubscriber);
		observers.subscribe(this.tBillDctUpdateSerFeeSubscriber);
		observers.subscribe(this.tBillReAprvMsgSubscriber);
	}

	private void confirmBillServiceFee(String dctId) {
		ValRetBiz valRetBiz = this.valRetBizService.selectByBizId(dctId);
		valRetBiz.setState("1");
		this.valRetBizService.updateNotNull(valRetBiz);
		CbDct dct = (CbDct) this.cbDctService.selectByKey(dctId);
		CbRec rec = (CbRec) this.cbRecService.selectByKey(dct.getBillId());
		CbOpt opt = new CbOpt();
		opt.setCurState(rec.getBillState());
		opt.setLimDate(rec.getExpDate());
		opt.setOptCode("EX19");
		opt.setRemark("������������������");

		Bill<CbDct> bill = new Bill();
		bill.setSource(dct);
		bill.setRec(rec);
		BillEvent<CbDct> event = new BillEvent(bill);
		event.setOperation(opt);
		Observable<BillEvent<CbDct>> observers = Observable.just(event);
		observers.subscribe(this.billOptSubscriber);
		observers.subscribe(this.billMoveSubscriber);
		observers.subscribe(this.billDctReAprvSignDebitCertSubscriber);
		observers.subscribe(this.billDctReAprvDeductSerFeeSubscriber);
		observers.subscribe(this.billDctUpdateSerFeeSubscriber);
		observers.subscribe(this.billReAprvMsgSubscriber);
	}
}
